package com.dji.sample.manage.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dji.sample.common.model.Pagination;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.util.KmlUtil;
import com.dji.sample.common.util.MinioUtil;
import com.dji.sample.common.util.kmlModel.TravelRecordRequest;
import com.dji.sample.manage.dao.DevicePlayLineInfoMapper;
import com.dji.sample.manage.dao.DevicePositionMapper;
import com.dji.sample.manage.dao.SysOrganizationMapper;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.entity.DevicePlayLineCacheEntity;
import com.dji.sample.manage.model.entity.DevicePlayLineEntity;
import com.dji.sample.manage.model.entity.DevicePositionEntity;
import com.dji.sample.manage.model.entity.SysOrganization;
import com.dji.sample.manage.service.DevicePlayLineCacheService;
import com.dji.sample.manage.service.DevicePlayLineInfoService;
import com.dji.sample.manage.service.DevicePositionService;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.wayline.dao.FlightPlanInfoMapper;
import com.dji.sample.wayline.dao.MemberUserMapper;
import com.dji.sample.wayline.model.entity.FlightPlanInfoEntity;
import com.dji.sample.wayline.service.FlightPlanInfoService;
import io.minio.ObjectWriteResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author yjt
 * @date 2022-09-09
 * @description:
 */
@Service
@Slf4j
public class DevicePlayLineInfoServiceImpl implements DevicePlayLineInfoService {

    @Autowired
    DevicePlayLineInfoMapper devicePlayLineInfoMapper;

    @Autowired
    DevicePositionMapper devicePositionMapper;

    @Autowired
    DevicePositionService devicePositionService;

    @Autowired
    DevicePlayLineCacheService devicePlayLineCacheService;

    @Autowired
    KmlUtil kmlUtil;

    @Autowired
    MinioUtil minioUtil;

    @Autowired
    IDeviceService deviceService;

    @Autowired
    SysOrganizationMapper sysOrganizationMapper;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    FlightPlanInfoService flightPlanInfoService;
    @Autowired
    FlightPlanInfoMapper flightPlanInfoMapper;

    @Autowired
    MemberUserMapper memberUserMapper;

    public static final String DEVICE_PLAY_LINE_KEY = "device:plan:line:";

    final SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public void save(DevicePlayLineEntity devicePlayLineEntity) {
        devicePlayLineInfoMapper.insert(devicePlayLineEntity);
    }

    @Override
    public void save(String deviceSn) {
        Optional<DeviceDTO> entity = deviceService.getDeviceBySn(deviceSn);
        if (entity.isPresent()) {
            DevicePlayLineEntity devicePlayLineEntity = new DevicePlayLineEntity(deviceSn);
            devicePlayLineEntity.setDeviceType(entity.get().getType() + "_" + entity.get().getSubType());
            devicePlayLineEntity.setOrgCode(entity.get().getOrgCode());
            devicePlayLineEntity.setOrgId(entity.get().getOrgId());
            devicePlayLineEntity.setFlag(0);
            devicePlayLineEntity.setDeviceNo(entity.get().getDeviceNo());
            devicePlayLineInfoMapper.insert(devicePlayLineEntity);
            //写入id
            stringRedisTemplate.opsForValue().set(DEVICE_PLAY_LINE_KEY + deviceSn, devicePlayLineEntity.getId().toString(), 2, TimeUnit.HOURS);
            return;
        }
        log.info("===设备不存在==={}", deviceSn);
    }

    @Override
    public DevicePlayLineEntity findLastDeviceLineInfo(String deviceSn) {
        return devicePlayLineInfoMapper.selectOne(new LambdaQueryWrapper<DevicePlayLineEntity>()
                .eq(DevicePlayLineEntity::getDeviceSn, deviceSn).eq(DevicePlayLineEntity::getFlag, 0).orderByDesc(DevicePlayLineEntity::getId).last("limit 1"));
    }

    @Override
    public void updatePosition(String deviceSn) {
        String id = stringRedisTemplate.opsForValue().get(DEVICE_PLAY_LINE_KEY + deviceSn);
        DevicePlayLineEntity devicePlayLineEntity = null;
        if (StringUtils.hasText(id)) {
            devicePlayLineEntity = devicePlayLineInfoMapper.selectById(Long.valueOf(id));
        }
        if (devicePlayLineEntity == null) {
            devicePlayLineEntity = findLastDeviceLineInfo(deviceSn);
        }
        if (devicePlayLineEntity == null) {
            log.error("==查询设备航线信息失败=={}", deviceSn);
            return;
        }
        if (devicePlayLineEntity.getEndPositionId() != null) {
            log.error("==航线信息已更新过=={}", devicePlayLineEntity.getId());
            return;
        }
        updatePosition(devicePlayLineEntity);
        devicePlayLineInfoMapper.updateById(devicePlayLineEntity);
        stringRedisTemplate.delete(DEVICE_PLAY_LINE_KEY + deviceSn);
    }

    @Override
    public void updateNullEndTime() {
        List<DevicePlayLineEntity> devicePlayLineEntities = devicePlayLineInfoMapper.selectList(new LambdaQueryWrapper<DevicePlayLineEntity>().eq(DevicePlayLineEntity::getFlag, 0).or().isNull(DevicePlayLineEntity::getFlag));
        for (DevicePlayLineEntity devicePlayLineEntity : devicePlayLineEntities) {
            updatePosition(devicePlayLineEntity);
            devicePlayLineInfoMapper.updateById(devicePlayLineEntity);
        }
    }


    public void updatePosition(DevicePlayLineEntity devicePlayLineEntity) {
        Calendar cal2 = Calendar.getInstance();
        List<DevicePositionEntity> list = devicePositionService.selectDevicePosition(devicePlayLineEntity.getDeviceSn(), dateTimeFormatter.format(devicePlayLineEntity.getCreateTime()));
        if (list.isEmpty() || list.size() <= 1) {
            //未结束 如果时间大于前一天 则默认无效数据
            cal2.setTime(devicePlayLineEntity.getCreateTime());
            if (Calendar.getInstance().get(Calendar.DAY_OF_WEEK) > cal2.get(Calendar.DAY_OF_WEEK)) {
                devicePlayLineEntity.setFlag(2);
            }
        } else {
            // 判断是什么计划类型
            String firstPlanId = null;
            String planIds = devicePlayLineEntity.getPlanIds();// 检查 planIds 是否为空或为 null
            if (planIds != null && !planIds.isEmpty()) {
                // 使用逗号分隔字符串并取第一个
                String[] ids = planIds.split(",");
                firstPlanId = ids[0]; // 取第一个 ID
                // 你现在可以使用 firstPlanId
                System.out.println("第一个计划 ID: " + firstPlanId);
            }
            FlightPlanInfoEntity planInfo = flightPlanInfoMapper.selectById(firstPlanId);
            if(null != planInfo){
                String type = planInfo.getType();
                devicePlayLineEntity.setType(type);
            }else {
                devicePlayLineEntity.setType("1");
            }

            devicePlayLineEntity.setStartPosition(list.get(0).getLongitude() + "," + list.get(0).getLatitude() + "," + list.get(0).getHeight());
            devicePlayLineEntity.setStartPositionId(list.get(0).getId().longValue());
            devicePlayLineEntity.setEndPosition(list.get(1).getLongitude() + "," + list.get(1).getLatitude() + "," + list.get(1).getHeight());
            devicePlayLineEntity.setEndPositionId(list.get(1).getId().longValue());
            devicePlayLineEntity.setEndTime(System.currentTimeMillis());

            devicePlayLineEntity.setFlag(1);
        }
    }

    @Override
    public String getLineOssUrl(Long id) throws Exception {
        DevicePlayLineCacheEntity devicePlayLineCacheEntity = devicePlayLineCacheService.findByLineId(id);
        if (devicePlayLineCacheEntity == null) {
            //先生成航线
            DevicePlayLineEntity entity = devicePlayLineInfoMapper.selectById(id);
            if (entity == null) {
                throw new IllegalArgumentException("数据不存在");
            }
            //查询所有点位列表
            List<DevicePositionEntity> list = devicePositionMapper.selectList(new LambdaQueryWrapper<DevicePositionEntity>().ge(DevicePositionEntity::getId, entity.getStartPositionId()).le(DevicePositionEntity::getId, entity.getEndPositionId()).eq(DevicePositionEntity::getDeviceSn, entity.getDeviceSn()));
            if (list.isEmpty()) {
                throw new IllegalArgumentException("未查询到轨迹点位数据");
            }
            String name = String.format("%s_%s", entity.getDeviceSn(), entity.getId());
            ObjectWriteResponse objectWriteResponse = kmlUtil.setTravelsKml(conventList(list), name);
            if (objectWriteResponse == null) {
                throw new IllegalArgumentException("航线获取失败");
            }
            devicePlayLineCacheService.save(new DevicePlayLineCacheEntity(id, objectWriteResponse.object(), new Date()));
            return minioUtil.preview(objectWriteResponse.object());
        }
        return minioUtil.preview(devicePlayLineCacheEntity.getObjectKey());
    }

    public List<TravelRecordRequest> conventList(List<DevicePositionEntity> list) {
        List<TravelRecordRequest> travelRecordRequests = new ArrayList<>();
        TravelRecordRequest travelRecordRequest = null;
        for (DevicePositionEntity devicePosition : list) {
            travelRecordRequest = new TravelRecordRequest(devicePosition.getLongitude(), devicePosition.getLatitude(), devicePosition.getHeight());
            travelRecordRequests.add(travelRecordRequest);
        }
        return travelRecordRequests;
    }

    @Override
    public PaginationData<DevicePlayLineEntity> findByDeviceSn(String deviceSn, Long page, Long pageSize) {
        Page<DevicePlayLineEntity> page1 = devicePlayLineInfoMapper.selectPage(new Page<>(page, pageSize), new LambdaQueryWrapper<DevicePlayLineEntity>().eq(DevicePlayLineEntity::getDeviceSn, deviceSn).eq(DevicePlayLineEntity::getFlag, 1).orderByDesc(DevicePlayLineEntity::getId));
        for (DevicePlayLineEntity record : page1.getRecords()) {
            if (record.getStartTime() != null) {
                record.setStanderStartTime(new Date(record.getStartTime()));
            }
            if (record.getEndTime() != null) {
                record.setStanderEndTime(new Date(record.getEndTime()));
            }
        }
        return new PaginationData<>(page1.getRecords(), new Pagination(page1));
    }

    @Override
    public PaginationData<DevicePlayLineEntity> page(Integer page, Integer pageSize, String searchKey, String orgCode) {
        Page<DevicePlayLineEntity> page1 = devicePlayLineInfoMapper.selectPage(new Page<>(page, pageSize), new LambdaQueryWrapper<DevicePlayLineEntity>().likeRight(DevicePlayLineEntity::getOrgCode, orgCode).eq(DevicePlayLineEntity::getFlag, 1).and(StringUtils.hasText(searchKey), lambdaQueryWrapper -> lambdaQueryWrapper.like(StringUtils.hasText(searchKey), DevicePlayLineEntity::getDeviceNo, searchKey).or().like(StringUtils.hasText(searchKey), DevicePlayLineEntity::getDeviceSn, searchKey)).orderByDesc(DevicePlayLineEntity::getId));
        for (DevicePlayLineEntity record : page1.getRecords()) {
            if (record.getStartTime() != null) {
                record.setStanderStartTime(new Date(record.getStartTime()));
            }
            if (record.getEndTime() != null) {
                record.setStanderEndTime(new Date(record.getEndTime()));
            }
        }
        if (page1.getRecords().isEmpty()) {
            return new PaginationData<>(page1.getRecords(), new Pagination(page1));
        }
        List<Long> orgIds = page1.getRecords().stream().map(DevicePlayLineEntity::getOrgId).collect(Collectors.toList());
        List<SysOrganization> list = sysOrganizationMapper.selectList(new LambdaQueryWrapper<SysOrganization>().select(SysOrganization::getOrgName, SysOrganization::getOrgId).in(SysOrganization::getOrgId, orgIds));
        for (DevicePlayLineEntity record : page1.getRecords()) {
            Optional<SysOrganization> sysOrganization = list.stream().filter(s -> s.getOrgId().equals(record.getOrgId())).findFirst();
            sysOrganization.ifPresent(organization -> record.setOrgName(organization.getOrgName()));
        }
        return new PaginationData<>(page1.getRecords(), new Pagination(page1));
    }

    @Override
    public DevicePlayLineEntity getById(Long id) {
        return devicePlayLineInfoMapper.selectById(id);
    }

    @Override
    public void updatePlanId(Long id, String planId,String account) {
        DevicePlayLineEntity devicePlayLineEntity = devicePlayLineInfoMapper.selectById(id);
        if (devicePlayLineEntity == null) {
            return;
        }
        DevicePlayLineEntity updateEntity = new DevicePlayLineEntity();
        updateEntity.setId(id);
        updateEntity.setAccount(account);
        updateEntity.setPlanIds(devicePlayLineEntity.getPlanIds() == null ? planId + "," : devicePlayLineEntity.getPlanIds() + planId + ",");
        devicePlayLineInfoMapper.updateById(updateEntity);
    }

    @Override
    public List<FlightPlanInfoEntity> getByLineId(Long id) {
        DevicePlayLineEntity devicePlayLineEntity = devicePlayLineInfoMapper.selectById(id);
        if (devicePlayLineEntity == null || !StringUtils.hasText(devicePlayLineEntity.getPlanIds())) {
            return new ArrayList<>();
        }
        List<Long> ids = Arrays.stream(devicePlayLineEntity.getPlanIds().split(",")).map(Long::valueOf).collect(Collectors.toList());
        List<FlightPlanInfoEntity> list = flightPlanInfoService.getByIds(ids);
        list.forEach(s->s.setPilotName(devicePlayLineEntity.getAccount()));
        return list;
    }
}
